<?php
// +----------------------------------------------------------------------
// | HkCms
// +----------------------------------------------------------------------
// | Copyright (c) 2020-2021 http://www.hkcms.cn, All rights reserved.
// +----------------------------------------------------------------------
// | Author: 广州恒企教育科技有限公司 <admin@hkcms.cn>
// +----------------------------------------------------------------------

declare (strict_types=1);

namespace app\index\taglib;

use think\template\TagLib;

class HkCms extends TagLib
{
    /**
     * 定义标签列表
     */
    protected $tags   =  [
        // 标签定义： attr 属性列表 close 是否闭合（1-闭合、0-开放） alias 标签别名 level 嵌套层次
        'channel'     => ['attr'=>'name,type,num,model,where,order,id,empty,currentstyle,cache,istotal,insub', 'close'=>1], // 获取栏目
        'breadcrumb'  => ['attr'=>'catid,symbol,class', 'close'=>0],// 面包屑导航
        'adv' => ['attr'=>'name,itemid,cache,id,empty,currentstyle,current', 'close'=>1], // 获取广告管理
        'content' => ['attr'=>'catid,model,order,num,where,page,more,id,empty,cache', 'close'=>1], // 模型内容列表
        'contentpage' => ['attr'=>'item,size,home,pre,next,last,mobile_item,name', 'close'=>0], // 设置分页格式
        'seo' => ['attr'=>'', 'close'=>0], // 生成SEO标签
        'pre' => ['attr'=>'catid,id,target,msg,field', 'close'=>0],//上一篇
        'next' => ['attr'=>'catid,id,target,msg,field', 'close'=>0],//下一篇
        'date' => ['attr'=>'name,format', 'close'=>0], // 日期格式化
        'volist' => ['attr'=>'name,id,offset,length,mod,empty,key,currentstyle,current', 'close'=>1], // 同tp的volist一致
        'guestbook' => ['attr'=>'catid', 'close'=>1]
    ];

    /**
     * 获取栏目列表
     * type='son' 获取下级栏目
     * type='peer' 表示同级栏目
     * type='top' 表示顶级栏目
     * @param $tag
     * @param $content
     * @return string
     */
    public function tagChannel($tag, $content)
    {
        $tag['id'] = !empty($tag['id']) ? $tag['id'] : 'item';
        $tag['currentstyle'] = !empty($tag['currentstyle']) ? $tag['currentstyle'] : 'active';
        $tag['empty'] = !empty($tag['empty']) ? $tag['empty'] : '';
        $tag['name'] = !empty($tag['name']) ? $tag['name'] : '';
        $tag['where'] = !empty($tag['where']) ? $this->parseCondition($tag['where']) : '';
        $tag['istotal'] = $tag['istotal'] ?? '';

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__LIST__ = (new \app\index\model\cms\Category)->getList('.self::arrToHtml($tag).');'."\r\n";
        $parseStr .= '$__CateInfo__ = $Cate ?? [];'."\r\n";
        $parseStr .= '?>';
        $parseStr .= '{volist name="__LIST__" id="'.$tag['id'].'" empty="'.$tag['empty'].'"}';
        $parseStr .= '{php}$'.$tag['id'].'["currentstyle"]=get_current($'.$tag['id'].', $__CateInfo__, "'.$tag['currentstyle'].'");{/php}';
        if ($tag['istotal']) {
            $parseStr .= '{php}$'.$tag['id'].'["total"]=get_doc_total($'.$tag['id'].');{/php}';
        }
        $parseStr .= $content;
        $parseStr .= '{/volist}';
        return $parseStr;
    }

    /**
     * 面包屑导航，catid,symbol-间隔符号,style-a标签的class 必须有一个
     * @param $tag
     * @return string
     */
    public function tagBreadcrumb($tag)
    {
        $tag['symbol'] = $tag['symbol'] ?? ' ';
        $tag['class']   = $tag['class'] ?? '';

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__CateInfo__ = $Cate ?? [];'."\r\n";
        $parseStr .= 'echo (new \app\index\model\cms\Category)->getBreadcrumb('.self::arrToHtml($tag).', $__CateInfo__);'."\r\n";
        $parseStr .= '?>';
        return $parseStr;
    }

    /**
     * 获取站点模块
     * @param $tag
     * @param $content
     * @return string
     */
    public function tagAdv($tag, $content)
    {
        $tag['id'] = !empty($tag['id']) ? $tag['id'] : 'item';
        $tag['empty'] = !empty($tag['empty']) ? $tag['empty'] : '';
        $tag['name'] = !empty($tag['name']) ? $tag['name'] : '';
        $tag['currentstyle'] = !empty($tag['currentstyle']) ? $tag['currentstyle'] : 'active';  // 选中的class
        $tag['current'] = !empty($tag['current']) ? $tag['current'] : 1;  // 默认第一张

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__LIST__ = (new \app\index\model\cms\Recommend)->getList('.self::arrToHtml($tag).');'."\r\n";
        $parseStr .= '?>';
        $parseStr .= '{volist name="__LIST__" id="'.$tag['id'].'" empty="'.$tag['empty'].'"}';
        $parseStr .= '{php}$'.$tag['id'].'["currentstyle"] = $i=="'.$tag['current'].'"?"'.$tag['currentstyle'].'":"";{/php}';
        $parseStr .= '{php}$'.$tag['id'].'["target"] = $'.$tag['id'].'["new_window"]==1?"target=_blank":"";{/php}';
        $parseStr .= $content;
        $parseStr .= '{/volist}';
        return $parseStr;
    }

    /**
     * 内容模型标签
     * @param $tag
     * @param $content
     * @return string
     */
    public function tagContent($tag, $content)
    {
        $tag['id'] = !empty($tag['id']) ? $tag['id'] : 'item';
        $tag['empty'] = !empty($tag['empty']) ? $tag['empty'] : '';
        $tag['where'] = !empty($tag['where']) ? $this->parseCondition($tag['where']) : '';
//        $tag['page'] = isset($tag['page']) ? ( (substr($tag['page'], 0, 1) == '$') ? $tag['page'] : (int) $tag['page'] ) : 1;
        $tag['page'] = $tag['page'] ?? 0;
        $tag['num'] = isset($tag['num']) ? ( (substr($tag['num'], 0, 1) == '$') ? $tag['num'] : (int) $tag['num'] ) : 10;

        // 是否包含下级
        $tag['insub'] = !isset($tag['insub']) || ($tag['insub']!=1 && $tag['insub']!=0)?1:$tag['insub'];

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__LIST__=[];'."\r\n";
        $parseStr .= '$__page__=null;'."\r\n";
        if (empty($tag['catid']) && empty($tag['model'])) {
            return '';
        } else if (!empty($tag['catid']) && empty($tag['model'])) { // 未指定模型的情况下
            if (!is_numeric($tag['catid']) && strpos($tag['catid'], '$') !== 0) {
                $tag['catid'] = "'{$tag['catid']}'";
            }
            $parseStr .= '$__categoryInfo__ = \app\index\model\cms\Category::where(["id"=>'.$tag['catid'].',"status"=>"normal"])->find();'."\r\n";
            $parseStr .= 'if (!empty($__categoryInfo__["model_id"])) {'."\r\n";
            $parseStr .=  '$__modelInfo__ = \app\admin\model\cms\Model::where(["status"=>"normal", "id"=>$__categoryInfo__["model_id"]])->find();'."\r\n";
            $parseStr .=  'if (!empty($__modelInfo__)) {'."\r\n";
            $parseStr .=  '$__action__ = "\app\admin\model\cms\\\".$__modelInfo__["controller"];'."\r\n";
            $parseStr .=  '$__LIST__ = (new $__action__)->handleTag('.self::arrToHtml($tag).', $__page__);'."\r\n";
            $parseStr .=  '}';
            $parseStr .=  '}';
        } else {
            if (!is_numeric($tag['model']) && strpos($tag['model'], '$') !== 0) {
                $tag['model'] = "'{$tag['model']}'";
            }
            $parseStr .= '$__modelInfo__ = \app\admin\model\cms\Model::where(["status"=>"normal", "id"=>'.$tag['model'].'])->find();'."\r\n";
            $parseStr .= 'if (!empty($__modelInfo__)) {'."\r\n";
            $parseStr .= '$__action__ = "\app\admin\model\cms\\\".$__modelInfo__["controller"];';
            $parseStr .= '$__LIST__ = (new $__action__)->handleTag('.self::arrToHtml($tag).', $__page__);'."\r\n";
            $parseStr .= '}';
        }

        $parseStr .= '?>';
        $parseStr .= '{volist name="__LIST__" id="'.$tag['id'].'" empty="'.$tag['empty'].'"}';
        $parseStr .= $content;
        $parseStr .= '{/volist}';
        return $parseStr;
    }

    /**
     * 设置分页格式
     * home-首页,pre-上一页,pageno-页码,next-下一页,last-尾页,info-数量信息,jump-跳转页码
     * size 属性指定多少个页码则显示省略号。至少6个。
     * @param $tag
     * @return string
     */
    public function tagContentpage($tag)
    {
        $tag['item'] = empty($tag['item']) ? 'pre,pageno,next' : $tag['item'];
        $tag['name'] = empty($tag['name']) ? '$__page__' : '$'.$tag['name'];
        if (request()->isMobile() && !empty($tag['mobile_item'])) {
            $tag['item'] = $tag['mobile_item'];
        }

        $parseStr = '<?php'."\r\n";
        $parseStr .= 'if (!empty('.$tag['name'].')) : '."\r\n";
        $parseStr .= 'echo '.$tag['name'].'->render('.self::arrToHtml($tag).');'."\r\n";
        $parseStr .= 'endif; ?>';
        return $parseStr;
    }

    /**
     * seo
     * @param $tag
     * @return string
     */
    public function tagSeo($tag)
    {
        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__SEO__ = "<title>".(empty($seo_title)?$site["home_title"]:$seo_title." - ".$site["title"])."</title>";'."\r\n";
        $parseStr .= '$__SEO__ .= "<meta name=\"keywords\" content=\"".(empty($seo_keywords)?$site["keyword"]:$seo_keywords)."\">";'."\r\n";
        $parseStr .= '$__SEO__ .= "<meta name=\"description\" content=\"".(empty($seo_desc)?$site["description"]:$seo_desc)."\">";'."\r\n";
        $parseStr .= 'echo $__SEO__;'."\r\n";
        $parseStr .= ' ?>';
        return $parseStr;
    }

    /**
     * 循环，主要用于内容页，支持多文件，多图片等数据的循环。
     * @param $tag
     * @param $content
     * @return string
     */
    public function tagVolist($tag, $content)
    {
        if (empty($tag['name'])) {
            return '';
        }

        $tag['id'] = $tag['id'] ?? 'item';
        $tag['offset'] = !empty($tag['offset']) && is_numeric($tag['offset']) ? intval($tag['offset']) : 0;
        $tag['length'] = !empty($tag['length']) && is_numeric($tag['length']) ? intval($tag['length']) : 'null';
        $tag['mod'] = $tag['mod'] ?? '2';
        $tag['empty'] = $tag['empty'] ?? '';
        $tag['key'] = $tag['key'] ?? 'i';

        $tag['currentstyle'] = !empty($tag['currentstyle']) ? $tag['currentstyle'] : 'active';  // 选中的class
        $tag['current'] = !empty($tag['current']) ? $tag['current'] : 1;  // 默认第一张

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__NAME__ = '.$this->autoBuildVar($tag['name'])."; \r\n";
        $parseStr .= 'if (!is_array($__NAME__) && ":"!=substr($__NAME__, 0, 1)) {'."\r\n";
        $parseStr .= '  $__NAME__ = explode(\',\', $__NAME__);'."\r\n";
        $parseStr .= '}'."\r\n";
        $parseStr .= '?>';
        $parseStr .= '{volist name="__NAME__" id="'.$tag['id'].'" offset="'.$tag['offset'].'" length="'.$tag['length'].'" mod="'.$tag['mod'].'" empty="'.$tag['empty'].'" key="'.$tag['key'].'" }';
        $parseStr .= '{php}$currentstyle = $i=="'.$tag['current'].'"?"'.$tag['currentstyle'].'":"";{/php}';
        $parseStr .= $content;
        $parseStr .= '{/volist}';
        return $parseStr;
    }

    /**
     * 上一篇标签
     * @param $tag
     * @return string
     */
    public function tagPre($tag)
    {
        if (empty($tag['catid']) || empty($tag['id'])) {
            return '';
        }
        // 显示字段
        $field = !empty($tag['field']) ? $tag['field'] : 'title';
        // 当没有内容时的提示语
        $msg = !empty($tag['msg']) ? $tag['msg'] : '已经没有了';
        // 是否新窗口打开
        $target = 'target='.(empty($tag['target'])?'':$tag['target']);

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__cat_info__ = (new \app\index\model\cms\Category)->getCateInfo('.$tag['catid'].');'."\r\n";;
        $parseStr .= 'if (!empty($__cat_info__) && !empty($__cat_info__["model_id"])) : '."\r\n";
        $parseStr .= '  $__model__ = \app\admin\model\cms\Model::where(["id"=>$__cat_info__["model_id"],"status"=>"normal"])->find();'."\r\n";
        $parseStr .= '  if (!empty($__model__)):'."\r\n";
        $parseStr .= '      $__controller__ = "\app\admin\model\cms\\\".$__model__->controller; '."\r\n";
        $parseStr .= '      $__INFO__ = (new $__controller__)->setTable($__model__->tablename)->where([\'category_id\'=>$__cat_info__[\'id\'],\'status\'=>\'normal\'])->where(\'id\',\'<\','.$tag['id'].')->order(["id"=>"DESC"])->find();'."\r\n";
        $parseStr .= '      if (empty($__INFO__)):'."\r\n";
        $parseStr .= '          echo "'.$msg.'"; '."\r\n";
        $parseStr .= '      else:'."\r\n";
        $parseStr .= '          $__INFO__ = $__INFO__->append(["url"])->toArray(); '."\r\n";
        $parseStr .= '          echo "<a href=".$__INFO__[\'url\']." '.$target.'>".$__INFO__["'.$field.'"]."</a>"; '."\r\n";
        $parseStr .= '      endif; '."\r\n";
        $parseStr .= '  endif; '."\r\n";
        $parseStr .= 'else: '."\r\n";
        $parseStr .= '  echo "'.$msg.'"; '."\r\n";
        $parseStr .= 'endif; ?>';
        return $parseStr;
    }

    /**
     * 下一篇标签
     * @param $tag
     * @return string
     */
    public function tagNext($tag)
    {
        if (empty($tag['catid']) || empty($tag['id'])) {
            return '';
        }
        // 显示字段
        $field = !empty($tag['field']) ? $tag['field'] : 'title';
        // 当没有内容时的提示语
        $msg = !empty($tag['msg']) ? $tag['msg'] : '已经没有了';
        // 是否新窗口打开
        $target = 'target='.(empty($tag['target'])?'':$tag['target']);

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__cat_info__ = (new \app\index\model\cms\Category)->getCateInfo('.$tag['catid'].');'."\r\n";;
        $parseStr .= 'if (!empty($__cat_info__) && !empty($__cat_info__["model_id"])) : '."\r\n";
        $parseStr .= '  $__model__ = \app\admin\model\cms\Model::where(["id"=>$__cat_info__["model_id"],"status"=>"normal"])->find();'."\r\n";
        $parseStr .= '  if (!empty($__model__)):'."\r\n";
        $parseStr .= '      $__controller__ = "\app\admin\model\cms\\\".$__model__->controller; '."\r\n";
        $parseStr .= '      $__INFO__ = (new $__controller__)->setTable($__model__->tablename)->where([\'category_id\'=>$__cat_info__[\'id\'],\'status\'=>\'normal\'])->where(\'id\',\'>\','.$tag['id'].')->order(["id"=>"asc"])->find();'."\r\n";
        $parseStr .= '      if (empty($__INFO__)):'."\r\n";
        $parseStr .= '          echo "'.$msg.'"; '."\r\n";
        $parseStr .= '      else:'."\r\n";
        $parseStr .= '          $__INFO__ = $__INFO__->append(["url"])->toArray(); '."\r\n";
        $parseStr .= '          echo "<a href=".$__INFO__[\'url\']." '.$target.'>".$__INFO__["'.$field.'"]."</a>"; '."\r\n";
        $parseStr .= '      endif; '."\r\n";
        $parseStr .= '  endif; '."\r\n";
        $parseStr .= 'else: '."\r\n";
        $parseStr .= '  echo "'.$msg.'"; '."\r\n";
        $parseStr .= 'endif; ?>';
        return $parseStr;
    }

    /**
     * 日期格式化
     * @param $tag
     * @param $content
     * @return string
     */
    public function tagDate($tag, $content)
    {
        if (empty($tag['name'])) {
            return '';
        }
        $tag['format'] = empty($tag['format'])?'Y-m-d':$tag['format'];
        $parseStr = '<?php'."\r\n";
        $parseStr .= 'echo get_date_format('.self::arrToHtml($tag).');'."\r\n";
        $parseStr .= '?>';
        return $parseStr;
    }

    public function tagGuestbook($tag, $content)
    {
        if (empty($tag['catid'])) {
            return '';
        }

        $parseStr = '<?php'."\r\n";
        $parseStr .= '$__fields__ = (new \app\admin\model\cms\Guestbook)->handleTag('.$tag['catid'].');'."\r\n";
        $parseStr .= ''."\r\n";

        $parseStr .= '?>';
        $parseStr .= $content;

        return $parseStr;
    }

    /**
     * 转换数据为HTML代码
     * @param $data
     * @return string
     */
    private static function arrToHtml($data)
    {
        if (is_array($data)) {
            $str = '[';
            foreach ($data as $key => $val) {
                if (is_array($val)) {
                    $str .= "'$key'=>" . self::arrToHtml($val) . ",";
                } else {
                    //如果是变量的情况
                    if (is_int($val)) {
                        $str .= "'$key'=>$val,";
                    } else if (strpos($val, '$') === 0) {
                        $str .= "'$key'=>$val,";
                    } else if (preg_match("/^([a-zA-Z_].*)\(/i", $val, $matches)) {//判断是否使用函数
                        if (function_exists($matches[1])) {
                            $str .= "'$key'=>$val,";
                        } else {
                            $str .= "'$key'=>'" . self::newAddslashes($val) . "',";
                        }
                    } else {
                        $str .= "'$key'=>'" . self::newAddslashes($val) . "',";
                    }
                }
            }
            $str = rtrim($str,',');
            return $str . ']';
        }
        return '';
    }

    /**
     * 返回经addslashes处理过的字符串或数组
     * @param string $string 需要处理的字符串或数组
     * @return mixed
     */
    private static function newAddslashes($string)
    {
        if (!is_array($string)) {
            return addslashes($string);
        }
        foreach ($string as $key => $val) {
            $string[$key] = self::newAddslashes($val);
        }
        return $string;
    }
}